// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: dom_ambiguity_test.cpp 317 2009-01-12 11:10:14Z heavyzheng $
//

#include <zzheng/xml/dom_ambiguity_test.hpp>
#include <zzheng/test_logging.hpp>
#include <zzheng/test_resource.hpp>
#include <zzheng/test_utility.hpp>

#include <zzheng/xml/dom.hpp>
#include <zzheng/xml/dom/utility.hpp>

#include <zzheng/utility/sys_env.hpp>
#include <zzheng/utility/boost_filesystem.hpp>

#ifdef ZZHENG_MSVC
#  pragma warning(push)
#  pragma warning(disable: 4127 4511 4512 4701)
#endif // ZZHENG_MSVC

#include <boost/lexical_cast.hpp>

#ifdef ZZHENG_MSVC
#  pragma warning(pop)
#endif // ZZHENG_MSVC

#include <boost/shared_ptr.hpp>
#include <exception>
#include <string>
#include <list>
#include <iostream>
#include <fstream>

namespace zzheng {
namespace test {

    namespace dom = zzheng::xml::dom; // namespace alias.

    ////////////////////////////////////////////////////////////////////////////////////////////////

    namespace {

        void xml_to_records(const dom::element& elem,
                            int level,
                            std::list<std::string>& records) {

            // Create a CSV record for the element.
            csv_record record;
            record << level
                   << elem.name()
                   << elem.uri()
                   << elem.attributes().size()
                   << elem.children().size();
            if (elem.children().size() == 1U && elem.children().begin()->type() == dom::text_node) {
                record << elem.content();
            } else {
                record << std::string();
            }
            records.push_back(record.str());

            // Create a CSV record for each attribute attached to this element.
            const dom::attribute_map& attrs = elem.attributes();
            for (dom::const_attribute_iterator i = attrs.begin(); i != attrs.end(); ++i) {
                record.clear();
                record << level
                       << ("@" + i->name())
                       << i->uri()
                       << std::string()
                       << std::string()
                       << i->value();
                records.push_back(record.str());
            }

            // Create CSV records recursively for the child elements.
            const dom::child_node_list& children = elem.children();
            for (dom::const_child_iterator i = children.begin(); i != children.end(); ++i) {
                if (i->type() == dom::element_node) {
                    xml_to_records( *dom::dynamic_node_cast<const dom::element>(i.ptr()),
                                    level + 1,
                                    records );
                }
            }
        }

    } // anonymous namespace 

    void test_declare_namespace() {

        info("Running test case: test_declare_namespace");

        const std::string URI_1 = "http://www.foo.com/uri/1/";
        const std::string URI_2 = "http://www.foo.com/uri/2/";
        const std::string URI_3 = "http://www.foo.com/uri/3/";

        dom::document doc;
        dom::element_ptr elem_1 = doc.reset_root(dom::make_element(URI_1, "elem_1"));
        elem_1->declare_namespace(URI_1);

        dom::element_ptr elem_2 = elem_1->children().push_back(dom::make_element(URI_2, "elem_2"));
        elem_2->declare_namespace(URI_3);

        dom::element_ptr elem_3 = elem_2->children().push_back(dom::make_element(URI_2, "elem_3"));
        dom::element_ptr elem_4 = elem_2->children().push_back(dom::make_element(URI_3, "elem_4"));
        dom::element_ptr elem_5 = elem_1->children().push_back(dom::make_element(URI_3, "elem_5"));

        std::cout << doc.str() << std::endl;

        std::list<std::string> records;
        xml_to_records(*doc.root(), 1, records);
        typedef std::list<std::string>::iterator iterator;
        for (iterator i = records.begin(); i != records.end(); ++i) {
            std::cout << *i << std::endl;
        }
    }

    void test_set_value() {

        dom::document doc;
        dom::element_ptr elem_1 = doc.reset_root(dom::make_element("elem_1"));
        dom::element_ptr elem_2 = elem_1->children().push_back(dom::make_element("elem_2"));
        std::pair<dom::attribute_ptr, bool> attr = elem_2->attributes().insert(
                dom::make_attribute("key", "value"));
        BOOST_CHECK(attr.second);
        dom::text_ptr txt = elem_2->children().push_back(dom::make_text(std::string()));
        std::cout << elem_1->str() << std::endl << std::endl;
        std::cout << elem_2->str() << std::endl << std::endl;
        std::cout << attr.first->str() << std::endl << std::endl;
        std::cout << txt->str() << std::endl << std::endl;
        std::cout << doc.str() << std::endl;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////

    void add_dom_ambiguity_test_cases(boost::unit_test::test_suite& suite) {
        suite.add( BOOST_TEST_CASE(&test_declare_namespace) );
        suite.add( BOOST_TEST_CASE(&test_set_value) );
    }


} // namespace zzheng::test
} // namespace zzheng





